home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / Visual Cafe Pro v1.0 / SOURCE.BIN / ComboBox.java < prev    next >
Encoding:
Java Source  |  1997-06-19  |  31.6 KB  |  1,115 lines

  1. package symantec.itools.awt;
  2.  
  3.  
  4. import java.awt.Color;
  5. import java.awt.Component;
  6. import java.awt.Dimension;
  7. import java.awt.Event;
  8. import java.awt.Font;
  9. import java.awt.Graphics;
  10. import java.awt.Image;
  11. import java.awt.Panel;
  12. import java.awt.TextField;
  13.  
  14. //    01/29/97    TWB    Integrated changes from Macintosh
  15. //    04/15/97    LAB Added 1 line in deselect() to clear
  16. //                    the textbox if deselect is called.
  17.  
  18.  
  19. /**
  20.  * ComboBox drop-down listbox component.
  21.  * @version 1.0, Nov 26, 1996
  22.  * @author Symantec
  23.  */
  24.  
  25. public class ComboBox
  26.     extends Panel
  27. {
  28.     /**
  29.      * Event ID used when the image part of a drop-down list item is selected.
  30.      */
  31.     public static final int EVT_IMAGE_SELECT = ImageListBox.EVT_IMAGE_SELECT;
  32.  
  33.     private boolean            bEditable;
  34.     private boolean            bSearchable;
  35.     private boolean            bCaseSensitive;
  36.     private TextField          editBox;
  37.     private DirectionButton    arrow;
  38.     private ImageListBox       list;
  39.     private boolean            bDown = false;
  40.     private int                ix;
  41.     private int                iy;
  42.     private int                iwidth;
  43.     private int                iheight;
  44.     private int                lheight;
  45.     private boolean            bOverList   = false;
  46.     private boolean            showHScroll = false;
  47.     private boolean            showVScroll = true;
  48.     private Font               editFont;
  49.     private Font               dropFont;
  50.     private static boolean     bOsFlag = false;
  51.     private static ComboBox    currentlyDown = null;
  52.     private Component          parent = null;
  53.     private String             sSearchText;
  54.     private String             sSearchItem;
  55.     private String             sLastText;
  56.     private String             sSearchOrig;
  57.     private int                searchIndex;
  58.     private int                searchLen;
  59.     private int                searchI;
  60.  
  61.     /**
  62.      * Constructs a new default ComboBox. The ComboBox is not editable and
  63.      * not searchable by default.
  64.      */
  65.     public ComboBox()
  66.     {
  67.         this(false, false);
  68.     }
  69.  
  70.     /**
  71.      * Constructs a new editable or searchable ComboBox.
  72.      * @param editable true = editable, false = non-editable
  73.      * @param searchable true = searchable, false = non-searchable
  74.      */
  75.     public ComboBox(boolean editable, boolean searchable)
  76.     {
  77.         bOsFlag = !System.getProperty("os.name").startsWith("Win");
  78.  
  79.         setLayout(null);
  80.         editBox = new TextField("");
  81.         editBox.setBackground(Color.white);
  82.  
  83.         arrow = new DirectionButton(DirectionButton.DOWN);
  84.         list = new ImageListBox("ILB");
  85.         list.setComboMode(true);
  86.         list.setShowHorizontalScroll(false);
  87.         add(list);
  88.         add(editBox);
  89.         add(arrow);
  90.         arrow.setShowFocus(false);
  91.         arrow.shrinkTriangle(1, 1, 5, 5);
  92.         arrow.disable();
  93.  
  94.         lheight = 0;
  95.         list.hide();
  96.  
  97.         setEditable(editable);
  98.         setSearchable(searchable);
  99.         bCaseSensitive = true;
  100.     }
  101.  
  102.     /**
  103.      * Conditionally set the ComboBox to be editable.
  104.      * @param editable true = editable, false = non-editable
  105.      * @see #getEditable
  106.      */
  107.     public void setEditable(boolean editable)
  108.     {
  109.         bEditable = editable;
  110.         editBox.setEditable(bEditable || bSearchable);
  111.     }
  112.  
  113.     /**
  114.      * Return the current ComboBox "editable" status.
  115.      * @return boolean - current editable status
  116.      * @see #setEditable
  117.      */
  118.     public boolean getEditable()
  119.     {
  120.         return bEditable;
  121.     }
  122.  
  123.     /**
  124.      * Conditionally set the ComboBox to be searchable.
  125.      * @param searchable true = searchable, false = non-searchable
  126.      * @see #getSearchable
  127.      */
  128.     public void setSearchable(boolean searchable)
  129.     {
  130.         bSearchable = searchable;
  131.         editBox.setEditable(bEditable || bSearchable);
  132.     }
  133.  
  134.     /**
  135.      * Returns the current ComboBox "searchable" status.
  136.      * @see #setSearchable
  137.      */
  138.     public boolean getSearchable()
  139.     {
  140.         return bSearchable;
  141.     }
  142.  
  143.     /**
  144.      * Conditionally set the ComboBox to be case sensitive during searches.
  145.      * @param bCaseSensitive true = case-sensitive, false = case-insensitive
  146.      * @see #getCaseSensitive
  147.      */
  148.     public void setCaseSensitive(boolean bCaseSensitive)
  149.     {
  150.         this.bCaseSensitive = bCaseSensitive;
  151.     }
  152.  
  153.     /**
  154.      * Returns the current ComboBox case-sensitive search status.
  155.      * @see #setSearchable
  156.      */
  157.     public boolean getCaseSensitive()
  158.     {
  159.         return bCaseSensitive;
  160.     }
  161.  
  162.     /**
  163.      * Sets whether or not the horizontal scrollbar should be made visible when
  164.      * necessary or should never be made visible.
  165.      * @param cond true = show when necessary, false = never show
  166.      * @see #getShowHorizontalScroll
  167.      */
  168.     public void setShowHorizontalScroll(boolean cond)
  169.     {
  170.         showHScroll = cond;
  171.         list.setShowHorizontalScroll(cond);
  172.     }
  173.  
  174.     /**
  175.      * Gets the current horizontal scrollbar display option.
  176.      * @return true if the horizontal scrollbar should be displayed when necessary,
  177.      * false if the scrollbar should never be shown.
  178.      * @see #setShowHorizontalScroll
  179.      */
  180.     public boolean getShowHorizontalScroll()
  181.     {
  182.         return showHScroll;
  183.     }
  184.  
  185.     /**
  186.      * Sets whether or not the vertical scrollbar should be made visible when
  187.      * necessary or should never be made visible.
  188.      * @param cond true = show when necessary, false = never show
  189.      * @see #getShowVerticalScroll
  190.      */
  191.     public void setShowVerticalScroll(boolean cond)
  192.     {
  193.         showVScroll = cond;
  194.         list.setShowVerticalScroll(cond);
  195.     }
  196.  
  197.     /**
  198.      * Gets the current vertical scrollbar display option.
  199.      * @return true if the vertical scrollbar should be displayed when necessary,
  200.      * false if the scrollbar should never be shown.
  201.      * @see #setShowVerticalScroll
  202.      */
  203.     public boolean getShowVerticalScroll()
  204.     {
  205.         return showVScroll;
  206.     }
  207.  
  208.     /**
  209.      * Set the edit field and drop-down list font.
  210.      * @param f new edit field and drop-down list font
  211.      * @see #getComboBoxFont
  212.      */
  213.     public synchronized void setComboBoxFont(Font f)
  214.     {
  215.         setFont(f);
  216.     }
  217.  
  218.     /**
  219.      * Get the edit field and drop-down font.
  220.      * @return current edit field and drop-down font
  221.      * @see #setComboBoxFont
  222.      */
  223.     public synchronized Font getComboBoxFont()
  224.     {
  225.         return editFont;
  226.     }
  227.  
  228.     /**
  229.      * Set the edit field font.
  230.      * @param f new edit field font
  231.      * @see #getEditFieldFont
  232.      */
  233.     public synchronized void setEditFieldFont(Font f)
  234.     {
  235.         if (editBox != null && f != null && iheight > 15)
  236.         {
  237.             editFont = f;
  238.             editBox.setFont(f);
  239.         }
  240.     }
  241.  
  242.     /**
  243.      * Get the edit field font.
  244.      * @return current edit field font
  245.      * @see #setEditFieldFont
  246.      */
  247.     public synchronized Font getEditFieldFont()
  248.     {
  249.         return editFont;
  250.     }
  251.  
  252.     /**
  253.      * Set the drop-down list font.
  254.      * @param f new drop-down list font
  255.      * @see #getDropDownFont
  256.      */
  257.     public synchronized void setDropDownFont(Font f)
  258.     {
  259.         if (list != null && f != null)
  260.         {
  261.             dropFont = f;
  262.             list.setFont(f);
  263.         }
  264.     }
  265.  
  266.     /**
  267.      * Get the drop-down list font.
  268.      * @return current drop-down list font
  269.      * @see #setDropDownFont
  270.      */
  271.     public synchronized Font getDropDownFont()
  272.     {
  273.         return dropFont;
  274.     }
  275.  
  276.     /**
  277.      * Processes events for this component.
  278.      * This is a standard Java AWT method which gets called by the AWT
  279.      * to handle this component's events. The default handler for 
  280.      * components dispatches to one of the following methods as needed:
  281.      * action(), gotFocus(), lostFocus(), keyDown(), keyUp(), mouseEnter(),
  282.      * mouseExit(), mouseMove(), mouseDrag(), mouseDown(), or mouseUp().
  283.      *
  284.      * @param evt the event to handle
  285.      * @return true if the event was handled and no further action is needed,
  286.      * false to pass the event to this component's parent
  287.      * @see java.awt.Component#action
  288.      * @see java.awt.Component#gotFocus
  289.      * @see java.awt.Component#lostFocus
  290.      * @see java.awt.Component#keyDown
  291.      * @see java.awt.Component#keyUp
  292.      * @see java.awt.Component#mouseEnter
  293.      * @see java.awt.Component#mouseExit
  294.      * @see java.awt.Component#mouseMove
  295.      * @see java.awt.Component#mouseDrag
  296.      * @see java.awt.Component#mouseDown
  297.      * @see java.awt.Component#mouseUp
  298.      */
  299.     public boolean handleEvent(Event evt)
  300.     {
  301.         switch (evt.id)
  302.         {
  303.             case Event.KEY_ACTION_RELEASE:
  304.             {
  305.                 if (evt.target != editBox)
  306.                 {
  307.                     switch(evt.key)
  308.                     {
  309.                         case Event.HOME:  list.select(0); break;
  310.                         case Event.END:   list.select(list.countItems() - 1); break;
  311.                         case Event.PGUP:
  312.                         case Event.UP:    list.select(list.getSelectedIndex() - 1); break;
  313.                         case Event.PGDN:
  314.                         case Event.DOWN:  list.select(list.getSelectedIndex() + 1); break;
  315.                     }
  316.  
  317.                     editBox.setText(list.getSelectedItem());
  318.                     editBox.selectAll();
  319.                 }
  320.                 break;
  321.             }
  322.  
  323.             case Event.KEY_PRESS:
  324.             {
  325.                 sLastText = editBox.getText();
  326.                 break;
  327.             }
  328.  
  329.             case Event.KEY_RELEASE:
  330.             {
  331.                 if (evt.target == editBox)
  332.                 {
  333.                     verify();
  334.                 }
  335.  
  336.                 break;
  337.             }
  338.  
  339.             case Event.GOT_FOCUS:
  340.             {
  341.                 if (evt.target == this && !bDown)
  342.                 {
  343.                     editBox.selectAll();
  344.                     editBox.requestFocus();
  345.                     break;
  346.                 }
  347.  
  348.                 if (bOsFlag)
  349.                 {
  350.                     if (evt.target == editBox)
  351.                     {
  352.                         dropList(false);
  353.                     }
  354.                 }
  355.  
  356.                 break;
  357.             }
  358.  
  359.             case Event.LOST_FOCUS:
  360.             {
  361.                 if ((evt.target == arrow) && !bOverList)
  362.                 {
  363.                     dropList(false);
  364.                 }
  365.  
  366.                 break;
  367.             }
  368.  
  369.             case Event.MOUSE_ENTER:
  370.             {
  371.                 if (evt.target == list)
  372.                 {
  373.                     bOverList = true;
  374.                 }
  375.  
  376.                 break;
  377.             }
  378.  
  379.             case Event.MOUSE_EXIT:
  380.             {
  381.                 if (evt.target == list)
  382.                 {
  383.                     bOverList = false;
  384.                 }
  385.  
  386.                 break;
  387.             }
  388.  
  389.             case Event.ACTION_EVENT:
  390.             {
  391.                 if (evt.target instanceof DirectionButton)
  392.                 {
  393.                     dropList(!bDown);
  394.  
  395.                     return true;
  396.                 }
  397.                 else if (evt.target == list) // ignore double-click
  398.                 {
  399.                     return true;
  400.                 }
  401.  
  402.                 break;
  403.             }
  404.  
  405.             case EVT_IMAGE_SELECT:
  406.             {
  407.                 if (parent == null)
  408.                 {
  409.                     parent = getParent();
  410.                 }
  411.  
  412.                 if (parent != null)
  413.                 {
  414.                     evt.target = this;
  415.                     parent.postEvent(evt);
  416.                 }
  417.  
  418.                 return true;
  419.             }
  420.  
  421.             case Event.LIST_SELECT:
  422.             {
  423.                 editBox.setText(list.getSelectedItem());
  424.  
  425.                 if (parent == null)
  426.                 {
  427.                     parent = getParent();
  428.                 }
  429.  
  430.                 if (parent != null)
  431.                 {
  432.                     evt.target = this;
  433.                     evt.id = Event.ACTION_EVENT;
  434.                     parent.postEvent(evt);
  435.                 }
  436.  
  437.                 dropList(false);
  438.                 return true;
  439.             }
  440.         }
  441.  
  442.         return super.handleEvent(evt);
  443.     }
  444.  
  445.     /**
  446.      * Return ComboBox top/down addition status.
  447.      * @return if true, add the ComboBox physically first, top to bottom, into
  448.      * the container which will be its parent.
  449.      * @see #addLastBottomUp
  450.      */
  451.     public static boolean addFirstTopDown()
  452.     {
  453.         return !addLastBottomUp();
  454.     }
  455.  
  456.     /**
  457.      * Return ComboBox bottom/up addition status.
  458.      * @return if true, add the ComboBox physically last, bottom to top, into
  459.      * the container which will be its parent.
  460.      * @see #addFirstTopDown
  461.      */
  462.     public static boolean addLastBottomUp()
  463.     {
  464.         String sOs = System.getProperty("os.name");
  465.  
  466.         if (sOs.startsWith("S") ||      // SunOS, Solaris
  467.            sOs.startsWith("Kona") ||   // Kona (Mr. Coffee)
  468.            sOs.startsWith("AIX") ||    // AIX
  469.            sOs.startsWith("OSF") )     // OSF
  470.         {
  471.             return true;
  472.         }
  473.  
  474.         // Windows Netscape 3.0bx
  475.         if (sOs.startsWith("Win") &&
  476.             System.getProperty("java.vendor").startsWith("Netscape") &&
  477.             System.getProperty("java.version").equals("1.02") )
  478.         {
  479.             return true;
  480.         }
  481.  
  482.         return false;
  483.     }
  484.  
  485.     /**
  486.      * Use this method to set a flag for use in your handleEvent to determine if
  487.      * the ComboBox needs help in "un-dropping".  This will improve useability
  488.      * under platforms which do not provide proper focus events.  (For best
  489.      * performance assign a variable in your class once to avoid repeated function
  490.      * calls to this method.)
  491.      * <pre>
  492.      *   boolean bNeedsPlatformHelp = ComboBox.needsPlatformHelp();
  493.      *
  494.      *   public boolean handleEvent(Event evt)
  495.      *   {
  496.      *       switch (evt.id)
  497.      *       {
  498.      *           case Event.MOUSE_UP:
  499.      *               // do it on mouse up, which indicates a full click somewhere other than
  500.      *               // the ComboBox that could be currently dropped down.
  501.      *               if (bNeedsPlatformHelp)
  502.      *                   ComboBox.unDropLastDropped();
  503.      *               break; // or other MOUSE_UP processing as necessary
  504.      *
  505.      *           ...
  506.      *
  507.      *       }
  508.      *
  509.      *       ...
  510.      *
  511.      *   }
  512.      * </pre>
  513.      * @see #unDropLastDropped
  514.      */
  515.     public static boolean needsPlatformHelp()
  516.     {
  517.         return bOsFlag;
  518.     }
  519.  
  520.     /**
  521.      * "un-drop" the last ComboBox that was dropped down.
  522.      * @see #needsPlatformHelp
  523.      */
  524.     public static void unDropLastDropped()
  525.     {
  526.         if (currentlyDown != null)
  527.         {
  528.             currentlyDown.dropList(false);
  529.         }
  530.     }
  531.  
  532.     /**
  533.      * Clear all items from the drop-down list.
  534.      */
  535.     public void clear()
  536.     {
  537.         list.clear();
  538.         editBox.setText("");
  539.     }
  540.  
  541.     /**
  542.      * Adds the specified item to the end of drop-down list and enable the item.
  543.      * @param item the item to be added
  544.      * @see #addItem(java.lang.String, boolean)
  545.      * @see #addItem(java.awt.Image, java.lang.String)
  546.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  547.      * @see #setListItems(java.lang.String[])
  548.      */
  549.     public synchronized void addItem(String item)
  550.     {
  551.         addItem((Image)null, item, true);
  552.     }
  553.  
  554.     /**
  555.      * Adds the specified item to the end of drop-down list and conditionally enable it.
  556.      * @param item the item to be added
  557.      * @param bEnabled whether or not the item is enabled
  558.      * @see #addItem(java.lang.String)
  559.      * @see #addItem(java.awt.Image, java.lang.String)
  560.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  561.      * @see #setListItems(java.lang.String[])
  562.      */
  563.     public synchronized void addItem(String item, boolean bEnabled)
  564.     {
  565.         addItem((Image)null, item, bEnabled);
  566.     }
  567.  
  568.     /**
  569.      * Adds the specified item with an image to the end of drop-down list and enables it.
  570.      * @param image the image to display on item line
  571.      * @param item the item to be added
  572.      * @see #addItem(java.lang.String)
  573.      * @see #addItem(java.lang.String, boolean)
  574.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  575.      * @see #setListItems(java.lang.String[])
  576.      */
  577.     public synchronized void addItem(Image image, String item)
  578.     {
  579.         addItem(image, item, true);
  580.     }
  581.  
  582.     /**
  583.      * Adds the specified item with an image to the end of drop-down list and
  584.      * conditionally enable it.
  585.      * @param image the image to display on item line
  586.      * @param item the item to be added
  587.      * @param bEnabled whether or not the item is enabled
  588.      * @see #addItem(java.lang.String)
  589.      * @see #addItem(java.lang.String, boolean)
  590.      * @see #addItem(java.awt.Image, java.lang.String)
  591.      * @see #setListItems(java.lang.String[])
  592.      */
  593.     public synchronized void addItem(Image image, String item, boolean bEnabled)
  594.     {
  595.         list.addItem(image, item, bEnabled);
  596.         arrow.enable();
  597.     }
  598.  
  599.     /**
  600.      * Adds the string array to the list.
  601.      * @param items items to add to the list
  602.      * @see #getListItems
  603.      * @see #addItem(java.lang.String)
  604.      * @see #addItem(java.lang.String, boolean)
  605.      * @see #addItem(java.awt.Image, java.lang.String)
  606.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  607.      */
  608.     public void setListItems(String[] items)
  609.     {
  610.         clear();
  611.         for (int i = 0; i < items.length; ++i)
  612.         {
  613.             addItem(items[i]);
  614.         }
  615.     }
  616.  
  617.     /**
  618.      * Returns the current list as a array.
  619.      * @see #setListItems
  620.      */
  621.     public String[] getListItems()
  622.     {
  623.         int len = countItems();
  624.         String[] items = new String[len];
  625.         for (int i = 0; i < len; ++i)
  626.         {
  627.             items[i] = getItem(i);
  628.         }
  629.         return items;
  630.     }
  631.  
  632.     /**
  633.      * Returns the number of items in the drop-down list.
  634.      */
  635.     public int countItems()
  636.     {
  637.         return list.countItems();
  638.     }
  639.  
  640.     /**
  641.      * Returns the drop-down item at the specified zero-relative index.
  642.      */
  643.     public String getItem(int index)
  644.     {
  645.         return list.getItem(index);
  646.     }
  647.  
  648.     /**
  649.      * Changes the image associated with a drop-down item.
  650.      * @param index the zero-relative index of the drop-down item
  651.      * @param image the image to associate with the drop-down item
  652.      */
  653.     public void changeImage(int index, Image image)
  654.     {
  655.         list.changeImage(index, image);
  656.     }
  657.  
  658.     /**
  659.      * Changes the text associated with a drop-down item.
  660.      * @param index the zero-relative index of the drop-down item
  661.      * @param text the text to associate with the drop-down item
  662.      */
  663.     public void changeText(int index, String text)
  664.     {
  665.         list.changeText(index, text);
  666.     }
  667.  
  668.     /**
  669.      * Enables a drop-down item at a given zero-relative list index.
  670.      * @param index the zero-relative index of the drop-down item
  671.      * @see #disable
  672.      */
  673.     public void enable(int index)
  674.     {
  675.         list.enable(index);
  676.     }
  677.  
  678.     /**
  679.      * Disables a drop-down item at a given zero-relative list index.
  680.      * @param index the zero-relative index of the drop-down item
  681.      * @see #enable
  682.      */
  683.     public void disable(int index)
  684.     {
  685.         list.disable(index);
  686.     }
  687.  
  688.     /**
  689.      * Conditionally enables a drop-down item at a given zero-relative list index.
  690.      * @param index the zero-relative index of the drop-down item
  691.      * @param cond item enable condition (true = enable, false = disable)
  692.      * @see #disable
  693.      */
  694.     public void enable(int index, boolean cond)
  695.     {
  696.         if (cond)
  697.         {
  698.             list.enable(index);
  699.         }
  700.         else
  701.         {
  702.             list.disable(index);
  703.         }
  704.     }
  705.  
  706.     /**
  707.      * Deletes an item from the drop-down list.
  708.      * @param position the zero-relative index of the item
  709.      * @see #addItem(java.lang.String)
  710.      * @see #addItem(java.lang.String, boolean)
  711.      * @see #addItem(java.awt.Image, java.lang.String)
  712.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  713.      * @see #setListItems(java.lang.String[])
  714.      */
  715.     public synchronized void delItem(int position)
  716.     {
  717.         delItems(position, position);
  718.     }
  719.  
  720.     /**
  721.      * Deletes multiple items from the drop-down list.
  722.      * (Note: the end position must be greater than or equal to the start position.)
  723.      * @param start the start zero-relative index of the items
  724.      * @param end the end zero-relative index of the items
  725.      * @see #addItem(java.lang.String)
  726.      * @see #addItem(java.lang.String, boolean)
  727.      * @see #addItem(java.awt.Image, java.lang.String)
  728.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  729.      * @see #setListItems(java.lang.String[])
  730.      */
  731.     public synchronized void delItems(int start, int end)
  732.     {
  733.         list.delItems(start, end);
  734.  
  735.         if (list.countItems() == 0)
  736.         {
  737.             arrow.disable();
  738.             dropList(false);
  739.         }
  740.     }
  741.  
  742.     /**
  743.      * Deletes the selected item from the list.
  744.      * @see #addItem(java.lang.String)
  745.      * @see #addItem(java.lang.String, boolean)
  746.      * @see #addItem(java.awt.Image, java.lang.String)
  747.      * @see #addItem(java.awt.Image, java.lang.String, boolean)
  748.      * @see #setListItems(java.lang.String[])
  749.      */
  750.     public synchronized void delSelectedItem()
  751.     {
  752.         list.delSelectedItems();
  753.     }
  754.  
  755.     /**
  756.      * Returns the text in the text field portion of the ComboBox, unless the ComboBox
  757.      * is not editable.
  758.      * @return edit field text (if editable) or null if ComboBox not editable
  759.      * @see #getSelectedItem
  760.      */
  761.     public String getText()
  762.     {
  763.         verify();
  764.         return editBox.getText();
  765.     }
  766.  
  767.     /**
  768.      * Returns the selected item on the drop-down list.
  769.      * @return text of selected item, or null if no item is selected
  770.      * @see #getText
  771.      * @see #getSelectedIndex
  772.      */
  773.     public String getSelectedItem()
  774.     {
  775.         return list.getSelectedItem();
  776.     }
  777.  
  778.     /**
  779.      * Gets the zero-relative index of the selected item in the drop-down list.
  780.      * @return zero-relative index of selection, or -1 if no item is selected
  781.      * @see #getSelectedItem
  782.      */
  783.     public int getSelectedIndex()
  784.     {
  785.         return list.getSelectedIndex();
  786.     }
  787.  
  788.     /**
  789.      * Selects the drop-down item with the specified zero-relative index.
  790.      * @param index the zero-relative index of the drop-down item to select
  791.      * @see #deselect
  792.      */
  793.     public synchronized void select(int index)
  794.     {
  795.         if (index >= 0 && index <= list.countItems())
  796.         {
  797.             list.select(index);
  798.             editBox.setText(list.getSelectedItem());
  799.  
  800.             if (bOsFlag)
  801.             {
  802.                 repaint();
  803.             }
  804.         }
  805.     }
  806.  
  807.     /**
  808.      * Selects the first drop-down item in the list which has exactly matching text.
  809.      * @param str the String to match
  810.      * @see #deselect
  811.      */
  812.     public void select(String str)
  813.     {
  814.         list.select(str);
  815.         editBox.setText(list.getSelectedItem());
  816.  
  817.         if (bOsFlag)
  818.         {
  819.             repaint();
  820.         }
  821.     }
  822.  
  823.     /**
  824.      * Deselects the drop-down item at the specified zero-relative index.
  825.      * @param index the zero-relative index of the drop-down item to deselect
  826.      * @see #deselect
  827.      */
  828.     public synchronized void deselect(int index)
  829.     {
  830.         list.deselect(index);
  831.         editBox.setText("");
  832.     }
  833.  
  834.     /**
  835.      * Returns the selection state for the given zero-relative index.
  836.      * @param index the zero-relative index of the drop-down item to be checked
  837.      * @return true if the drop-down item at the specified index has been
  838.      * selected; false otherwise
  839.      * @see #select
  840.      */
  841.     public synchronized boolean isSelected(int index)
  842.     {
  843.         return list.isSelected(index);
  844.     }
  845.  
  846.     /**
  847.      * Sets this component's text font.
  848.      * This is a standard Java AWT method which gets called to change
  849.      * the font used for drawing text in this component.
  850.      * In this case the text is in the edit field and the drop-down list.
  851.      * @param f the new font to use for drawing text
  852.      * @see java.awt.Component#getFont
  853.      */
  854.     public synchronized void setFont(Font f)
  855.     {
  856.         editFont = dropFont = f;
  857.         setEditFieldFont(f);
  858.         setDropDownFont(f);
  859.         super.setFont(f);
  860.     }
  861.  
  862.     /**
  863.      * Handles dropping and "un-dropping" the ComboBox list.
  864.      * @param bDown true to drop the list, false to "un-drop" the list.
  865.      */
  866.     public void dropList(boolean bDown)
  867.     {
  868.         if (this.bDown == bDown)
  869.         {
  870.             return;
  871.         }
  872.  
  873.         this.bDown = bDown;
  874.  
  875.         if (bDown)
  876.         {
  877.             if (currentlyDown != null && currentlyDown != this)
  878.             {
  879.                 currentlyDown.dropList(false);
  880.             }
  881.  
  882.             currentlyDown = this;
  883.             list.show();
  884.             list.setDirty();
  885.             list.repaint();
  886.  
  887.             if (getParent() != null)
  888.             {
  889.                 lheight = Math.min(getParent().bounds().height - iy - iheight - 10, list.minimumSize().height + 3);
  890.             }
  891.             else
  892.             {
  893.                 lheight = list.minimumSize().height + 3;
  894.             }
  895.  
  896.             arrow.setDirection(DirectionButton.UP);
  897.         }
  898.         else
  899.         {
  900.             lheight = 0;
  901.             currentlyDown = null;
  902.             list.hide();
  903.             arrow.setDirection(DirectionButton.DOWN);
  904.             invalidate();
  905.         }
  906.         arrow.repaint();
  907.         super.reshape(ix, iy, iwidth, iheight + lheight);
  908.     }
  909.  
  910.     /**
  911.      * Moves and/or resizes this component.
  912.      * This is a standard Java AWT method which gets called to move and/or 
  913.      * resize this component. Components that are in containers with layout
  914.      * managers should not call this method, but rely on the layout manager
  915.      * instead.
  916.      * 
  917.      * @param x horizontal position in the parent's coordinate space
  918.      * @param y vertical position in the parent's coordinate space
  919.      * @param width the new width
  920.      * @param height the new height
  921.      */
  922.     public synchronized void reshape(int x, int y, int width, int height)
  923.     {
  924.         ix = x;
  925.         iy = y;
  926.         iwidth = width;
  927.  
  928.         if (bOsFlag)
  929.         {
  930.             iheight = Math.max(29, height);
  931.         }
  932.         else
  933.         {
  934.             iheight = height;
  935.         }
  936.  
  937.         if (height > 22)
  938.         {
  939.             height -= 22;
  940.  
  941.             if (bOsFlag)
  942.             {
  943.                 x = y = 7;
  944.             }
  945.             else
  946.             {
  947.                 x = y = 5;
  948.             }
  949.  
  950.             while(height > 0)
  951.             {
  952.                 x++;
  953.                 height--;
  954.  
  955.                 if (height > 0)
  956.                 {
  957.                     y++;
  958.                     height--;
  959.                 }
  960.             }
  961.  
  962.             arrow.shrinkTriangle(1, 1, x, y);
  963.         }
  964.         else
  965.         {
  966.             arrow.shrinkTriangle(1, 1, 5, 5);
  967.         }
  968.  
  969.         super.reshape(ix, iy, iwidth, iheight + lheight);
  970.     }
  971.  
  972.     /**
  973.      * Paints this component using the given graphics context.
  974.      * This is a standard Java AWT method which typically gets called
  975.      * by the AWT to handle painting this component. It paints this component
  976.      * using the given graphics context. The graphics context clipping region
  977.      * is set to the bounding rectangle of this component and its <0,0>
  978.      * coordinate is this component's top-left corner.
  979.      * 
  980.      * @param g the graphics context used for painting
  981.      * @see java.awt.Component#repaint
  982.      * @see java.awt.Component#update
  983.      */
  984.     public void paint(Graphics g)
  985.     {
  986.         super.paint(g);
  987.         Dimension s = size();
  988.  
  989.         if (bDown)
  990.         {
  991.             list.reshape(0, iheight+1, s.width, lheight);
  992.         }
  993.  
  994.         if (symantec.itools.lang.OS.isMacintosh())  
  995.             editBox.reshape(0,(int)(iheight* 0.1), s.width-16,(int)(iheight*0.8));
  996.         else
  997.             editBox.reshape(0,0, s.width-16, iheight);  
  998.         
  999.         editBox.setText(list.getSelectedItem()); // so we can get an item to show
  1000.                                                 // w/o an event (see constructor) - Andy
  1001.        
  1002.         if (symantec.itools.lang.OS.isMacintosh())  
  1003.              arrow.reshape(s.width-16,(int)(iheight* 0.1), 15, (int)(iheight*0.8));
  1004.         else
  1005.         {
  1006.             if (bOsFlag)
  1007.             {
  1008.                 arrow.reshape(s.width-16, 2, 15, iheight-4);
  1009.             }
  1010.                 else
  1011.                 {
  1012.                     arrow.reshape(s.width-16, 1, 15, iheight-2);
  1013.                }
  1014.         }
  1015.     }
  1016.  
  1017.     /**
  1018.      * Returns the recommended dimensions to properly display this component.
  1019.      * @return the preferred size with the specified number of rows if the
  1020.      * row size is greater than 0.
  1021.      */
  1022.     /**
  1023.      * Returns the recommended dimensions to properly display this component.
  1024.      * This is a standard Java AWT method which gets called to determine
  1025.      * the recommended size of this component. 
  1026.      *
  1027.      * @see #minimumSize
  1028.      */
  1029.     public Dimension preferredSize()
  1030.     {
  1031.         Dimension s = size();
  1032.         Dimension d = minimumSize();
  1033.  
  1034.         return new Dimension(Math.max(s.width, d.width), Math.max(s.height, d.height));
  1035.     }
  1036.  
  1037.     /**
  1038.      * Returns the minimum dimensions to properly display this component.
  1039.      * This is a standard Java AWT method which gets called to determine
  1040.      * the minimum size of this component. 
  1041.      * Considerations include the number of rows in the list.
  1042.      * @see #preferredSize
  1043.      */
  1044.     public Dimension minimumSize()
  1045.     {
  1046.         Dimension d = editBox.minimumSize();
  1047.         d.width += 17;
  1048.         if (d.height == 0)
  1049.         {
  1050.             if (bOsFlag)
  1051.             {
  1052.                 d.height = 29;
  1053.             }
  1054.             else
  1055.             {
  1056.                 d.height = 21;
  1057.             }
  1058.         }
  1059.  
  1060.         return d;
  1061.     }
  1062.  
  1063.     private void verify()
  1064.     {
  1065.         if (bSearchable == true)
  1066.         {
  1067.             searchIndex = editBox.getSelectionStart();
  1068.             sSearchOrig = editBox.getText().substring(0, searchIndex);
  1069.  
  1070.             if (bCaseSensitive)
  1071.             {
  1072.                 sSearchText = sSearchOrig;
  1073.             }
  1074.             else
  1075.             {
  1076.                 sSearchText = sSearchOrig.toUpperCase();
  1077.             }
  1078.  
  1079.             searchLen = list.countItems();
  1080.  
  1081.             if (sSearchText.length() > 0)
  1082.             {
  1083.                 for(searchI = 0; searchI < searchLen; ++searchI)
  1084.                 {
  1085.                     if (bCaseSensitive)
  1086.                     {
  1087.                         sSearchItem = list.getItem(searchI);
  1088.                     }
  1089.                     else
  1090.                     {
  1091.                         sSearchItem = list.getItem(searchI).toUpperCase();
  1092.                     }
  1093.  
  1094.                     if (sSearchItem.startsWith(sSearchText))
  1095.                     {
  1096.                         editBox.setText(sSearchOrig);
  1097.                         list.select(searchI);
  1098.                         editBox.select(searchIndex, searchIndex);
  1099.                         break;
  1100.                     }
  1101.                 }
  1102.  
  1103.                 if (!bEditable && (searchI == searchLen)) // !editable && search failed
  1104.                 {
  1105.                     editBox.setText(sLastText);
  1106.                     editBox.select(searchIndex-1, searchIndex-1);
  1107.                 }
  1108.             }
  1109.         }
  1110.  
  1111.         sLastText = editBox.getText();
  1112.     }
  1113. }
  1114.  
  1115.